package com.symaster.common.swing.element;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 叠加面板
 *
 * @author yinmiao
 * @version 2022-12-28 18:59
 */
public class OverlayPane extends JPanel {

    private Component comp;
    private List<ComponentConfig> componentConfigs;

    public OverlayPane() {
        setLayout(null);
    }

    public void setRoot(Component comp) {
        this.comp = comp;
        super.add(comp);
    }

    public void add(Component comp, LayoutEnum layoutEnum, int... marge) {
        if (componentConfigs == null) {
            componentConfigs = new ArrayList<>();
        }
        ComponentConfig componentConfig = new ComponentConfig();
        componentConfig.comp = comp;
        componentConfig.layoutEnum = layoutEnum;
        componentConfig.marge = marge;
        componentConfigs.add(componentConfig);
        super.add(comp);
        setComponentZOrder(comp, 0);
    }

    @Override
    public Component add(Component comp) {
        throw new IllegalArgumentException("请使用 add(Component comp, LayoutEnum layoutEnum, int... marge)");
    }

    @Override
    public Component add(String name, Component comp) {
        throw new IllegalArgumentException("请使用 add(Component comp, LayoutEnum layoutEnum, int... marge)");
    }

    @Override
    public Component add(Component comp, int index) {
        throw new IllegalArgumentException("请使用 add(Component comp, LayoutEnum layoutEnum, int... marge)");
    }

    @Override
    public void add(Component comp, Object constraints) {
        throw new IllegalArgumentException("请使用 add(Component comp, LayoutEnum layoutEnum, int... marge)");
    }

    @Override
    public void add(Component comp, Object constraints, int index) {
        throw new IllegalArgumentException("请使用 add(Component comp, LayoutEnum layoutEnum, int... marge)");
    }

    @Override
    public void paint(Graphics g) {
        Rectangle bounds = getBounds();
        if (bounds != null) {
            setupRootLayout(bounds);
            setupComponentConfigsLayout(bounds);
        }
        super.paint(g);
    }

    private void setupComponentConfigsLayout(Rectangle bounds) {
        if (componentConfigs == null || componentConfigs.size() == 0) {
            return;
        }
        componentConfigs.forEach(e -> {
            Component comp = e.comp;
            Dimension size = getComponentSize(comp);
            int width = size.width;
            int height = size.height;

            int[] marge = getMarge(e.marge);

            if (LayoutEnum.LEFT_TOP.equals(e.layoutEnum)) {
                comp.setBounds(marge[0], marge[1], width, height);

            } else if (LayoutEnum.RIGHT_TOP.equals(e.layoutEnum)) {
                int x = (int) Math.round(bounds.getWidth() - width);
                comp.setBounds(x - marge[0], marge[1], width, height);

            } else if (LayoutEnum.LEFT_BOTTOM.equals(e.layoutEnum)) {
                int y = (int) Math.round(bounds.getHeight() - height);
                comp.setBounds(marge[0], y - marge[1], width, height);

            } else if (LayoutEnum.RIGHT_BOTTOM.equals(e.layoutEnum)) {
                int x = (int) Math.round(bounds.getWidth() - width);
                int y = (int) Math.round(bounds.getHeight() - height);
                comp.setBounds(x - marge[0], y - marge[1], width, height);

            }
        });
    }

    private Dimension getComponentSize(Component comp) {
        return comp.getPreferredSize();
    }

    private int[] getMarge(int[] marge) {
        if (marge == null || marge.length == 0) {
            return new int[]{0, 0};
        }
        if (marge.length >= 2) {
            return new int[]{marge[0], marge[1]};
        }
        return new int[]{marge[0], 0};
    }

    private void setupRootLayout(Rectangle bounds) {
        if (comp == null) {
            return;
        }
        comp.setBounds(0, 0, bounds.width, bounds.height);
    }

    private static class ComponentConfig {
        private Component comp;
        private LayoutEnum layoutEnum;
        private int[] marge;
    }

    public enum LayoutEnum {
        LEFT_TOP(0),
        RIGHT_TOP(1),
        LEFT_BOTTOM(2),
        RIGHT_BOTTOM(3),
        ;

        private final int code;

        LayoutEnum(int code) {
            this.code = code;
        }

        public int getCode() {
            return code;
        }
    }
}
